/*
 *  Copyright (C) 2009 Antonio Mata Chamorro
 *  
 *  Este programa es software libre: usted puede redistribuirlo y/o modificarlo
 *  bajo los t�rminos de la Licencia P�blica General GNU publicada
 *  por la Fundaci�n para el Software Libre, ya sea la versi�n 3
 *  de la Licencia, o (a su elecci�n) cualquier versi�n posterior.
 *  
 *  Este programa se distribuye con la esperanza de que sea �til, pero 
 *  SIN GARANT�A ALGUNA; ni siquiera la garant�a impl�cita
 *  MERCANTIL o de APTITUD PARA UN PROP�SITO DETERMINADO. 
 *  Consulte los detalles de la Licencia P�blica General GNU para obtener 
 *  una informaci�n m�s detallada. 
 *  
 *  Deber�a haber recibido una copia de la Licencia P�blica General GNU
 *  junto a este programa. 
 *  En caso contrario, consulte <http://www.gnu.org/licenses/>.
 *   
 */
package org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas;

import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.alineacion.AlineacionTierAI;
import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.detalle.TacticaDetalleBase;
import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.detalle.TacticaDetalleDefensas;
import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.detalle.TacticaDetalleDelanteros;
import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.detalle.TacticaDetallePrecision;
import org.javahispano.javacup.tacticas_aceptadas.amata.com.amata.javacup.tacticas.detalle.TacticaDetalleVelocidad;

/**
 * Esta clase contiene todos los par�metros que configuran como se comporta un
 * equipo y sus jugadores. Esta clase es pasada en el contructor de las clases
 * {@link SoccerPlayer} y {@link SoccerTeam} para configurarlos. Estos
 * par�metros se han fijado utilizando un algoritmo genetico: se hacia competir
 * distintos equipos con configuraciones generadas aleatoriamente. Los equipos
 * que obtenian mejores puntuaci�nes pasan a la siguiente generacion (o la
 * siguiente ronda de la competicion). Los valores de la configuracion se mutan
 * puntualmente y se cruzan para obtener nuevas configuraciones.
 * <p/>
 * Despu�s de repetir este proceso durante un conjunto de generaciones se obtuvo
 * los valores fijados en esta clase por defecto.
 * 
 * @author Antonio Mata Chamorro
 * */
public class SoccerMatchConfiguration {
	// configuracion de TacticaTierAI
	private int indexDetalle = 4; // 0;
	private int indexAlineacion = 6; // 0;

	// configuracion para StrikeCalculator
	private float kickElevation = 24.043001f;

	// configuracion para AutoPassSpotCalculator
	private float autoPassDegradationWeight = 0.8402473f;
	private float opponentMinDistance = 7.3806877f;
	private float defenderMinDistance = 5.014721f;

	// configuracion para SupportSpotCalculator
	private int verticalSlice = 8;
	private int horizontalSlice = 8;
	private float minPassDistance = 10.598209f;
	private float maxPassDistance = 71.39757f;
	private float passDegradationWeight = 0.5554207f;
	private float defenderMinDistanceInPass = 3.514254f;

	// configuracion para SoccerTeam
	private int numDefenders = 1;
	private int numSupporters = 4;
	private float distanceForAttack = 9.454916f;
	private float distanceForDefense = 18.865408f;

	// configuracion para SoccerPlayer
	private float autoPassForce = 0.7021151f;
	private float passForce = 0.4786923f;
	private int stepsWaitingForBall = 5;
	private float stabilizationFactorForStrike = 0.50281423f;
	private float stabilizationFactorForPass = 0.05179443f;

	// mas configuracion para StrikeCalculator
	private float dirtyStrikeFactor = 1f;

	/**
	 * Fija la elevacion vertical con la que se disparar la pelota cuando un
	 * jugador trate de tirar a puerta.
	 * 
	 * @return numero de angulos de elevacion vertical de la pelota
	 * */
	public float getKickElevation() {
		return kickElevation;
	}

	public void setKickElevation(float kickElevation) {
		this.kickElevation = kickElevation;
	}

	/**
	 * Este par�metro permite fijar como de peligroso consideramos que es
	 * realizar un autopase por defecto. El valor del autopase seleccionado se
	 * multiplica por este factor.
	 * */
	public float getAutoPassDegradationWeight() {
		return autoPassDegradationWeight;
	}

	public void setAutoPassDegradationWeight(float autoPassDegradationWeight) {
		this.autoPassDegradationWeight = autoPassDegradationWeight;
	}

	/**
	 * Distancia m�nima a la que un jugador contrario debe de estar de la pelota
	 * despu�s de realizar el autopase el jugador actual. Si esta mas cerca el
	 * autopase se desestima.
	 * */
	public float getOpponentMinDistance() {
		return opponentMinDistance;
	}

	public void setOpponentMinDistance(float opponentMinDistance) {
		this.opponentMinDistance = opponentMinDistance;
	}

	/**
	 * Distancia m�nima a la que debe estar un jugador contrario del jugador
	 * actual. Si un jugador contrario esta mas cerca que defenderMinDistance el
	 * autopase se desestimaria (siempre se fijara con un valor 0)
	 * */
	public float getDefenderMinDistance() {
		return defenderMinDistance;
	}

	public void setDefenderMinDistance(float defenderMinDistance) {
		this.defenderMinDistance = defenderMinDistance;
	}

	/**
	 * Porciones verticales en la que el campo de juego se divide para
	 * considerar {@link Spot} para eval�ar pase.
	 * */
	public int getVerticalSlice() {
		return verticalSlice;
	}

	public void setVerticalSlice(int verticalSlice) {
		this.verticalSlice = verticalSlice;
	}

	/**
	 * Porciones horizontales en la que el campo de juego se divide para
	 * considerar {@link Spot} para eval�ar pase.
	 * */
	public int getHorizontalSlice() {
		return horizontalSlice;
	}

	public void setHorizontalSlice(int horizontalSlice) {
		this.horizontalSlice = horizontalSlice;
	}

	/**
	 * Distancia m�nima de pase para un jugador. Si la distancia entre el
	 * jugador y un cierto punto es menor que esta distancia este punto no se
	 * considerara para realizar un pase. Esto permite desestimar puntos de pase
	 * que hace avanzar muy poco al equipo.
	 * */
	public float getMinPassDistance() {
		return minPassDistance;
	}

	public void setMinPassDistance(float minPassDistance) {
		this.minPassDistance = minPassDistance;
	}

	/**
	 * Distancia m�xima de pase para un jugador. Si la distancia entre el
	 * jugador y un cierto punto es mayor que esta distancia este punto no se
	 * considerara para realizar un pase. Esto permite desestimar puntos de pase
	 * estan demasiado lejor del jugador para que la pelota llegue hasta all�.
	 * */
	public float getMaxPassDistance() {
		return maxPassDistance;
	}

	public void setMaxPassDistance(float maxPassDistance) {
		this.maxPassDistance = maxPassDistance;
	}

	/**
	 * Este factor es una estimaci�n de las posibilidades de que un pase salga
	 * mal en un equipo. Cuando se hace un pase el valor que se le da a un pase
	 * depende de las posibilidades de marcar desde el nuevo punto al que
	 * llegaria la pelota. Este valor se multiplica por este factor e indica las
	 * posibilidades de que el pase sea fall�do.
	 * 
	 * @return 0 todos los pases son considerados como fall�dos (y por lo tanto
	 *         no se estimara que ningun pase vaya a salir bien), 1 todos los
	 *         pase salen correctamente y no hay posibilidad de perder la pelota
	 * */
	public float getPassDegradationWeight() {
		return passDegradationWeight;
	}

	public void setPassDegradationWeight(float passDegradationWeight) {
		this.passDegradationWeight = passDegradationWeight;
	}

	/**
	 * Un posible pase sera desestimado si despu�s del pase la distancia de un
	 * jugador contrario a la pelota es menor que este par�metro
	 * */
	public float getDefenderMinDistanceInPass() {
		return defenderMinDistanceInPass;
	}

	public void setDefenderMinDistanceInPass(float defenderMinDistanceInPass) {
		this.defenderMinDistanceInPass = defenderMinDistanceInPass;
	}

	/**
	 * Numero de jugadores que van a colocarse en las posibles posiciones de
	 * pase del contrario, cuando el equipo oponente controla el bal�n
	 * */
	public int getNumDefenders() {
		return numDefenders;
	}

	public void setNumDefenders(int numDefenders) {
		this.numDefenders = numDefenders;
	}

	/**
	 * Numero de jugadores que van a colocarse en las posibles posiciones de
	 * pase cuando un jugador del propio equipo controla el bal�n
	 * */
	public int getNumSupporters() {
		return numSupporters;
	}

	public void setNumSupporters(int numSupporters) {
		this.numSupporters = numSupporters;
	}

	/**
	 * El {@link SoccerTeam} considera que hay que colocar a los jugadores en
	 * posicion de ofensiva si alg�n {@link SoccerPlayer} controla el bal�n y el
	 * jugador esta en su propio campo y a menos de esta distancia de la mitad
	 * del campo, o mas adelantado
	 * */
	public float getDistanceForAttack() {
		return distanceForAttack;
	}

	public void setDistanceForAttack(float distanceForAttack) {
		this.distanceForAttack = distanceForAttack;
	}

	/**
	 * El {@link SoccerTeam} considera que hay que colocar a los jugadores en
	 * posicion de defensiva si alg�n {@link SoccerPlayer} del equipo contrario
	 * controla el bal�n y este esta en el campo contrario y a menos de esta
	 * distancia de la mitad del campo, o mas adelantado
	 * */
	public float getDistanceForDefense() {
		return distanceForDefense;
	}

	public void setDistanceForDefense(float distanceForDefense) {
		this.distanceForDefense = distanceForDefense;
	}

	/**
	 * Fuerza con la que el jugador golpea la pelota para correr con ella
	 * controlada. Este par�metro se fija para todos los jugadores de un equipo.
	 * El valor concreto de fuerza dependera de las caracteristicas de jugador
	 * (JugadorDetalle)
	 * */
	public float getAutoPassForce() {
		return autoPassForce;
	}

	public void setAutoPassForce(float autoPassForce) {
		this.autoPassForce = autoPassForce;
	}

	/**
	 * Fuerza con la que el jugador pasa la pelota a otro compa�ero. Este
	 * par�metro se fija para todos los jugadores de un equipo. El valor
	 * concreto de fuerza dependera de las caracteristicas de jugador
	 * (JugadorDetalle)
	 * */
	public float getPassForce() {
		return passForce;
	}

	public void setPassForce(float passForce) {
		this.passForce = passForce;
	}

	/**
	 * Numero de pasos de juego que un jugador que esta esperando un pase
	 * espera. Si no recibe la pelota en el estado "esperando por el pelota" en
	 * este numero de paso cambia al estado "esperando"
	 * */
	public int getStepsWaitingForBall() {
		return stepsWaitingForBall;
	}

	public void setStepsWaitingForBall(int stepsWaitingForBall) {
		this.stepsWaitingForBall = stepsWaitingForBall;
	}

	/**
	 * Degradacion que se le aplica al valor de un tiro a puerta (strike) si no
	 * ha habido un autopase anterior. Permite que la velocidad de la pelota se
	 * reduzca y por lo tanto se reduzca la posibilidad de error. Este par�metro
	 * toma valores de 0 a 1. Si vale 1 no habra autopase ante del tiro, si vale
	 * 0 siempre debe haber autopase antes del tiro
	 * */
	public float getStabilizationFactorForStrike() {
		return stabilizationFactorForStrike;
	}

	public void setStabilizationFactorForStrike(
			float stabilizationFactorForStrike) {
		this.stabilizationFactorForStrike = stabilizationFactorForStrike;
	}

	/**
	 * Degradacion que se le aplica al valor de un pase si no ha habido un
	 * autopase anterior. Permite que la velocidad de la pelota se reduzca y por
	 * lo tanto se reduzca la posibilidad de error. Este par�metro toma valores
	 * de 0 a 1. Si vale 1 no habra autopase ante del pase, si vale 0 siempre
	 * debe haber autopase antes del pase
	 * */
	public float getStabilizationFactorForPass() {
		return stabilizationFactorForPass;
	}

	public void setStabilizationFactorForPass(float stabilizationFactorForPass) {
		this.stabilizationFactorForPass = stabilizationFactorForPass;
	}

	/**
	 * Indice que permite escoger el conjunto de JugadorDetalle que utilizara
	 * {@link TacticaTierAI}. Este indice su utilizara en el m�todo
	 * {@link TacticaTierAI#getDetalle()} para extraer la correcta alineacion.
	 * Los posibles valores para esta alineacion son:
	 * <ul>
	 * <li>0: {@link TacticaDetalleBase}</li>
	 * <li>1: {@link TacticaDetalleDefensas}</li>
	 * <li>2: {@link TacticaDetalleDelanteros}</li>
	 * <li>3: {@link TacticaDetallePrecision}</li>
	 * <li>4: {@link TacticaDetalleVelocidad}</li>
	 * </ul>
	 * */
	public int getIndexDetalle() {
		return indexDetalle;
	}

	public void setIndexDetalle(int indexDetalle) {
		this.indexDetalle = indexDetalle;
	}

	/**
	 * Indice que permite escoger el conjunto de alineaciones que utiliza el
	 * equipo empleado por {@link TacticaTierAI}. Las posiciones de estas
	 * alineaciones se extraeran llamando a los m�todos
	 * {@link AlineacionTierAI#getDefensivePositions(int)},
	 * {@link AlineacionTierAI#getOffensivePositions(int)} y
	 * {@link AlineacionTierAI#getKickOffPositions(int)}
	 * */
	public int getIndexAlineacion() {
		return indexAlineacion;
	}

	public void setIndexAlineacion(int indexAlineacion) {
		this.indexAlineacion = indexAlineacion;
	}

	@Override
	public String toString() {
		String res = super.toString() + ",indexDetalle                 ="
				+ indexDetalle + ",indexAlineacion              ="
				+ indexAlineacion + ",kickElevation                ="
				+ kickElevation + ",autoPassDegradationWeight    ="
				+ autoPassDegradationWeight + ",opponentMinDistance          ="
				+ opponentMinDistance + ",defenderMinDistance          ="
				+ defenderMinDistance + ",verticalSlice                ="
				+ verticalSlice + ",horizontalSlice              ="
				+ horizontalSlice + ",minPassDistance              ="
				+ minPassDistance + ",maxPassDistance              ="
				+ maxPassDistance + ",passDegradationWeight        ="
				+ passDegradationWeight + ",defenderMinDistanceInPass    ="
				+ defenderMinDistanceInPass + ",numDefenders                 ="
				+ numDefenders + ",numSupporters                ="
				+ numSupporters + ",distanceForAttack            ="
				+ distanceForAttack + ",distanceForDefense           ="
				+ distanceForDefense + ",autoPassForce                ="
				+ autoPassForce + ",passForce                    =" + passForce
				+ ",stepsWaitingForBall          =" + stepsWaitingForBall
				+ ",stabilizationFactorForStrike ="
				+ stabilizationFactorForStrike
				+ ",stabilizationFactorForPass   ="
				+ stabilizationFactorForPass + ",dirtyStrikeFactor			   ="
				+ dirtyStrikeFactor + "";

		return res;
	}

	public void setDirtyStrikeFactor(float dirtyStrikeFactor) {
		this.dirtyStrikeFactor = dirtyStrikeFactor;
	}

	public float getDirtyStrikeFactor() {
		return dirtyStrikeFactor;
	}
}
